import hashlib
import time
from logging.handlers import RotatingFileHandler

from flask import json, request, session, jsonify
from flask_cors import CORS
import json;
import os;
import logging

from controllers.lib.AliMqttApi import AliMqttApi
from db.mysql.MySql import MySql
from framework.CRedis import CRedis
from framework.EException import EException
from flask import Flask


#from services.MemberActivityRecordService import MemberActivityRecordService
#from services.MemberService import MemberService


alimqtt = Flask(__name__)
alimqtt.config['SECRET_KEY'] = os.urandom(24)  # 生成24位的随机数种子，用于产生SESSION ID
alimqtt.config['JSON_AS_ASCII'] = False


env_dist = os.environ # environ是在os.py中定义的一个dict environ = {}
signKey="";
resisAdd=env_dist.get('resisAdd');
if (resisAdd==None):
    #resisAdd="860000000.api.yq30.com"
    resisAdd = "xyj01.yingjiayun.com"

redisPwd=env_dist.get('redisPwd');
if (redisPwd==None):
    #redisPwd="MqybafrJ4TSSbCRJ5xr9"
    redisPwd = "07e9bc89-b869-11ec-a8fa-00163e0176fa"
redisPort=env_dist.get('redisPort');
if (redisPort==None):
    #redisPwd="MqybafrJ4TSSbCRJ5xr9"
    redisPort = 6380

db_user=env_dist.get('db_user');
if (db_user==None):
    db_user="root"
db_pwd=env_dist.get('db_pwd');
if (db_pwd==None):
    db_pwd="Yingjia@123"
db_name=env_dist.get('db_name');
if (db_name==None):
    db_name="api"
db_add=env_dist.get('db_add');
if (db_add==None):
    db_add="xyjdb.yingjiayun.com"

mySql=MySql(db_add,db_user,db_pwd,db_name)
redis =CRedis(host=resisAdd, port=6379, password=redisPwd, db=0, decode_responses=True)

logging.basicConfig(level=logging.DEBUG)
#日志
def setup_log():
    """配置日志"""
    #datetime.datetime.strptime(string,'%Y-%m-%d %H:%M:%S')
    # 设置日志的记录等级
    logging.basicConfig(level=logging.DEBUG)  # 调试debug级
    # 创建日志记录器，指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
    file_log_handler = RotatingFileHandler("logs/log.log", maxBytes=1024 * 1024 * 100, backupCount=10)
    # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)
    # 为全局的日志工具对象（flask app使用的）添加日志记录器
    logging.getLogger().addHandler(file_log_handler)

#全局可跨域请求
CORS(alimqtt, supports_credentials=True)
CORS(alimqtt, resources=r'/*')

@alimqtt.before_request
def before():
    """
    针对app实例定义全局拦截器
    """
    url = request.path  # 读取到当前接口的地址
    s="http[{0}]:{1}".format(request.method,request.url)
    if request.method=="POST":
        s=s+"\n\t请求参数：{0}".format(request.json);
    logging.info(s);

    tenantId= request.headers.get('tenant-id');
    if (tenantId==None):
        result = {
            "message": "请求非法",
            "code": 600
        };
        return result;

    #验证商户
    if redis.get(tenantId)==None:
        tenantInfo= mySql.selectOne('select * from bis_tenant where id=\''+tenantId+'\'');
        if (tenantInfo==None):
            result = {
                        "message": "此商户不存在",
                        "code": 601
                    };
            return result;
        redis.set(tenantId,json.dumps(tenantInfo));
    tenantInfo=json.loads(redis.get(tenantId));
    #验证必传参数
    try:
        if request.method == "POST":
            data=request.json;
            checkJsonKey(data,'timestamp','sign')
        else:
            if (request.args.get('timestamp')==None):
                raise EException(603,"请求参数不完整【timestamp】")
            if (request.args.get('sign')==None):
                raise EException(603,"请求参数不完整【sign】")
    except EException as e:
        return {
            "code": e.args[0],
            "message": e.args[1]
        }
    #验证签名
    if request.method == "POST":
        data = request.json;
    else:
        data = {};
        for key in request.args.keys():
            data[key]=request.args.get(key)

    sign=sign_JsonBody(data,tenantInfo["sign_key"])
    if (sign!=data["sign"]):
        return {
            "code": 604,
            "message": '签名非法'
        }
    if url == '/sess':
        pass
    elif session.get('is_login', '') != 'true':
        #return '你还没有登录'
        pass
    else:
        pass

# MD5加密
def jiamimd5(src):
    m = hashlib.md5()
    m.update(src.encode('UTF-8'))
    return m.hexdigest()

def sign_JsonBody(body, signKey):
    '''请求body sign签名'''
    # 列表生成式，生成key=value格式
    #a = ["".join(i) for i in body.items() if i[1] and i[0] != "sign"]
    jsonData =json.loads(json.dumps(body))

    if ('sign' in jsonData):
        jsonData.pop('sign')
    d1 = json.dumps(jsonData, sort_keys=True, indent=4,separators=(',',':'));
    #print(d1)
    jsonData=json.loads(d1);
    a="";
    for key in jsonData:
        a=a+key+"="+str(jsonData[key])+"&";
    #a=a[:-1];
    #print(a)
    # 参数名ASCII码从小到大排序
    #strA = a+"sign=""".join(sorted(a))
    # 在strA后面拼接上apiKey得到striSignTemp字符串
    striSignTemp = a+"sign="+signKey
    sign = jiamimd5(striSignTemp.lower())
    # 得到sign签名后新的body值
    #body["sign"] = sign
    #return body
    return sign

@alimqtt.after_request
def after(response):
    if response.status_code==200:
        if (response.is_json):
            js=response.json;
            if ("code" in js):
                js["timestamp"]=int(time.time());
                js["success"] = False;
                result=js;
            else:
                result = {
                    "success": True,
                    "message": "",
                    "code": response.status_code,
                    "result": js,
                    "timestamp": int(time.time())
                };
            tenantId = request.headers.get('tenant-id');
            info=redis.get(tenantId);
            if tenantId!=None and info!=None:
                tenantInfo = json.loads(info);
                signKey=tenantInfo["sign_key"]
            sign=sign_JsonBody(result,signKey);
            result["sign"]=sign
            response = jsonify(result);
    logging.info("\t返回信息："+str(response.json));
    return response;

def checkJsonKey(json, *keys):
    if (len(keys)==0):
        raise EException(602,"参数错误");
    for key in keys:
        if (key not in json):
            raise EException(603,"请求参数不完整【%s】" % key);

#会员登录
@alimqtt.route('/QueryDeviceDetail',methods=['post'])
def post_QueryDeviceDetail():
    try:
        checkJsonKey(request.json,"productkey","deviceName")
        tenantInfo=json.loads(redis.get(request.headers.get('tenant-id')))
        mqttapi = AliMqttApi(tenantInfo["ali_key_id"], tenantInfo["ali_key_secret"],tenantInfo["region_id"])
        productkey= request.json['productkey'];
        deviceName = request.json['deviceName'];

        res= mqttapi.QueryDeviceDetail(productkey,deviceName)
        return res;
    except EException as e:
        return {
            "code": e.args[0],
            "message": e.args[1]
        }

@alimqtt.route('/RegisterDevice',methods=['post'])
def post_RegisterDevice():
    try:
        checkJsonKey(request.json, "productkey", "deviceName","nickName")
        tenantInfo=json.loads(redis.get(request.headers.get('tenant-id')))
        mqttapi = AliMqttApi(tenantInfo["ali_key_id"], tenantInfo["ali_key_secret"],tenantInfo["region_id"])
        res= mqttapi.RegisterDevice(request.json['productkey'],request.json['deviceName'],request.json['nickName'])
        return res;
    except EException as e:
        return {
            "code": e.args[0],
            "message": e.args[1]
        }


